--------------------------------------------------------------
-- 荣耀峡谷（龙族战场）跨服逻辑
--------------------------------------------------------------

local LuaMongo = _G.lua_mongo
local DB = require("common.DB")
local Lang = require("common.Lang")
local Util = require("common.Util")
local InnerMsg = require("core.InnerMsg")
local CombatDefine = require("combat.CombatDefine")
local MiddleLogic = require("middle.MiddleLogic")
local MiddleManager = require("middle.MiddleManager")
local RoleLogic = require("role.RoleLogic")
local ValleyLogic = require("valley.ValleyLogic")

local QueryByUuid = {_id = nil}
local FieldsRoleBase = {rolebase = 1}
local FilldsCombatLog = {attacker = 1, defender = 1, isWin = 1, time = 1, tili1 = 1, tili2 = 1}
local DBUpdateField = {}	
local MAX_BOARD_LEN = 50

-- 获取活动服基础信息
function getMainInfo(svrIndex)
	if not svrIndex then return end
	local commonDB = ValleyLogic.getCommonDB()
	if not commonDB.mainInfos then
		return
	end
	return commonDB.mainInfos[svrIndex]
end

-- 保存活动服基础信息
function saveMainInfo(svrIndex, data)
	local commonDB = ValleyLogic.getCommonDB()
	commonDB.mainInfos = commonDB.mainInfos or {}
	commonDB.mainInfos[svrIndex] = Util.copyTable(data)
	ValleyLogic.saveCommonDB(commonDB)
end

-- 获取参赛者信息
function getPlayerData(uuid, fields)
	if not uuid then return end
	QueryByUuid._id = uuid
	LuaMongo.find(DB.db_valley, QueryByUuid, fields)
	local playerData = {}
	return LuaMongo.next(playerData) and playerData
end

-- 保存/更新参赛者信息
function updatePlayerData(playerData)
	local oldData = getPlayerData(playerData._id)
	if not oldData then
		-- 首次收到，插入数据
		LuaMongo.insert(DB.db_jjcLadder, playerData)
		return true
	else
		-- 非首次，更新数据九  零 一  起玩 www.9 01  7 5.com 
		QueryByUuid._id = playerData._id
		LuaMongo.update(DB.db_jjcLadder, QueryByUuid, playerData)
	end	
end

-- 刷新部分数据
function upsetPlayerData(playerData)
	if not playerData._id then return end
	QueryByUuid._id = playerData._id
	DBUpdateField["$set"] = playerData
	LuaMongo.update(DB.db_jjcLadder, QueryByUuid, DBUpdateField)
end

-- 获取鼓舞选择的选项
function getInspireIndex(mainInfo, uuid)
	if not mainInfo then return end
	if not mainInfo.inspireList then return end
	return mainInfo.inspireList[uuid]
end

-- 设置鼓舞选择的选项
function setInspireIndex(mainInfo, uuid, index)
	if not mainInfo then return end
	mainInfo.inspireList = mainInfo.inspireList or {}
	mainInfo.inspireList[uuid] = index
	mainInfo.inspireCnt = (mainInfo.inspireCnt or 0) + 1
	ValleyLogic.saveCommonDB(ValleyLogic.getCommonDB())
end

-- 是否有日志红点
function hasLogRed(mainInfo, uuid)
	if not mainInfo then return end
	if not mainInfo.logs or #mainInfo.logs < 1 then
		return 
	end
	return (not mainInfo.logReads[uuid])
end

-- 记录已读
function setLogRead(mainInfo, uuid)
	if not mainInfo then return end
	if mainInfo.logReads[uuid] then
		return
	end
	mainInfo.logReads[uuid] = true
	return true
end

-- 获取战斗记录
function getCombatInfo(videoUuid, field)
	if not videoUuid then return end
	QueryByUuid._id = videoUuid 
	LuaMongo.find(DB.db_valley_record, QueryByUuid, field)
	local combatInfo = {}
	return LuaMongo.next(combatInfo) and combatInfo
end

-- 添加记录
function addLog(combatInfo, mainInfo1, mainInfo2)
	LuaMongo.insert(DB.db_valley_record, combatInfo)
end

-- 处理日志
function solveLog(camp, mainInfo, combatInfo, playerData)
	mainInfo.logReads = {} 
	table.insert(mainInfo.logs, 1, combatInfo._id)

	local isWin = combatInfo.isWin 
	if camp == CombatDefine.ATTACK_SIDE then
		isWin = not combatInfo.isWin 
	end 
	if isWin then
		mainInfo.fightWinCnt = mainInfo.fightWinCnt + 1
	end
	if isWin ~= true or playerData.rolebase.tili < 1 then
		mainInfo.fightIndexChange = mainInfo.fightIndexChange or {}
		mainInfo.fightIndexChange[combatInfo.roadIndex] = true
	end
	mainInfo.fightResult = mainInfo.fightResult or {}
	mainInfo.fightResult[combatInfo.roadIndex] = isWin
	mainInfo.fightVideo = mainInfo.fightVideo or {}
	mainInfo.fightVideo[combatInfo.roadIndex] = combatInfo._id
end

-- 获取已行军时间
function getMoveTime()
	local _, roundState, roundStateEndTime = ValleyLogic.getRound()
	if roundState ~= ValleyLogic.STATE_FIGHT_MOVE then
		return 0
	end
	return ValleyLogic.roundMoveTime - (roundStateEndTime - os.time())
end

-- 获取x路第y个移动中角色的uuid
function getMovePlayerUuid(mainInfo, roadIndex, index)
	if not mainInfo then return end
	local roadList = mainInfo.roadList[roadIndex]
	if not roadList then return end 

	local fightIndexStart = mainInfo.fightIndexList[roadIndex] or 1
	local fightIndex = fightIndexStart + index - 1
	local uuid = roadList[fightIndex]
	return uuid
end

-- 目标点
function getMoveToPos(index)
	return ValleyLogic.ROAD_POINT_CNT - index + 1
end

-- 获取移动中的对象结构体
function getMovePlayer(mainInfo, camp, roadIndex, index)
	local uuid = getMovePlayerUuid(mainInfo, roadIndex, index)
	local playerData = getPlayerData(uuid, FieldsRoleBase)
	if not playerData then return end

	local movePlayer = {}
	movePlayer.camp = camp 
	movePlayer.roadIndex = roadIndex
	movePlayer.startPos = mainInfo.moveList[uuid] or 0
	movePlayer.moveToPos = getMoveToPos(index)
	movePlayer.moveTime = getMoveTime()
	movePlayer.moveTimeMax = ValleyLogic.roundMoveTime
	movePlayer.name = playerData.rolebase.name 
	movePlayer.body = playerData.rolebase.body
	return movePlayer
end

-- 是否所有战斗都结束了
function isAllFightEnd(mainInfo)
	if not mainInfo then return true end
	
	for roadIndex = 1, ValleyLogic.ROAD_MAX_CNT do
		if getMovePlayerUuid(mainInfo, roadIndex, 1) then
			return 
		end
	end
	return true
end

-- 复制发送到logic的mainInfo
function copyWLMainInfo(mainInfo)
	if not mainInfo then return end
	local tMainInfo = {}
	tMainInfo.svrIndex = mainInfo.svrIndex
	tMainInfo.svrName = mainInfo.svrName
	tMainInfo.inspireCnt = mainInfo.inspireCnt
	tMainInfo.fightIndexList = mainInfo.fightIndexList
	tMainInfo.roadList = mainInfo.roadList
	return tMainInfo
end

-------------------------------------- middle -------------------------------------------

-- 接收活动服基础信息
function LW_VALLEY_MAIN_INFO(fd, data)
	local svrIndex = MiddleManager.FD_2_SVRINDEX[fd]
	if not svrIndex then return end

	saveMainInfo(svrIndex, data)
end

-- 接收玩家信息
function LW_VALLEY_ROAD_PLAYER(fd, playerData)
	local svrIndex = MiddleManager.FD_2_SVRINDEX[fd]
	if not svrIndex then return end
	
	local data = getMainInfo(svrIndex)
	if not data then return end

	local roadIndex = playerData.roadIndex
	local isFirst = updatePlayerData(playerData)
	if isFirst then
		data.roadList = data.roadList or {}
		data.roadList[roadIndex] = data.roadList[roadIndex] or {}
		local len = #data.roadList[roadIndex]
		data.roadList[roadIndex][len + 1] = playerData._id
		saveMainInfo(svrIndex, data)
	end
end

-- 查询主界面信息
function LW_VALLEY_QUERY(fd, uuid)
	local svrIndex1 = MiddleManager.FD_2_SVRINDEX[fd]
	if not svrIndex1 then return end

	local state, leftTime = ValleyLogic.getState()
	local msgInner = InnerMsg.wl.WL_VALLEY_QUERY
	msgInner.uuid = uuid
	local data = {}	
	if state == ValleyLogic.STATE_ACT_FIGHT then
		local mainInfo1 = getMainInfo(svrIndex1)
		local svrIndex2 = mainInfo1 and mainInfo1.targetSvrIndex
		local mainInfo2 = getMainInfo(svrIndex2)
		local round, roundState, roundStateEndTime = ValleyLogic.getRound()
		if isAllFightEnd(mainInfo1) or isAllFightEnd(mainInfo2) then -- 战斗提前结束
			roundState = STATE_FIGHT_END
		end
		data.mainInfo1 = copyWLMainInfo(mainInfo1)
		data.mainInfo2 = copyWLMainInfo(mainInfo2) 
		data.round = round
		data.roundState = roundState
		data.roundStateEndTime = roundStateEndTime
		data.logRed = hasLogRed(mainInfo1, uuid) 

		-- 移动中的对象
		data.players = {}
		for roadIndex = 1, ValleyLogic.ROAD_MAX_CNT do
			for i = 1, ValleyLogic.ROAD_POINT_CNT do
				local movePlayer1 = getMovePlayer(mainInfo1, CombatDefine.ATTACK_SIDE, roadIndex, index)
				data.players[#data.players + 1] = movePlayer1

				local movePlayer2 = getMovePlayer(mainInfo2, CombatDefine.DEFEND_SIDE, roadIndex, index)
				data.players[#data.players + 1] = movePlayer2
			end
		end				
	else
		data.state = state
		data.leftTime = leftTime
	end
	msgInner.data = data
	InnerMsg.sendMsg(fd, msgInner)
end

function fontRoadPlayer(uuid)
	local playerData = getPlayerData(uuid)
	if not playerData then return end

	local net = {}
	net.uuid = uuid
	net.name = playerData.rolebase.name 
	net.tili = playerData.rolebase.tili
	net.zhandouli = playerData.rolebase.zhandouli
	net.heroList = {[0] = 0}
	for index, obj in pairs(playerData.objList) do
		net.heroList[0] = net.heroList[0] + 1
		local heroNet = net.heroList[net.heroList[0]]
		HeroGrid.makeHeroSimple(heroNet, obj, index)
	end
	return net
end

-- 营地查看
function LW_VALLEY_ROAD_QUERY(fd, uuid, camp, roadIndex)
	local svrIndex1 = MiddleManager.FD_2_SVRINDEX[fd]
	if not svrIndex1 then return end

	local mainInfo1 = getMainInfo(svrIndex1)
	local svrIndex2 = mainInfo1 and mainInfo1.targetSvrIndex
	local mainInfo2 = getMainInfo(svrIndex2)
	local roadList = nil
	if camp == CombatDefine.ATTACK_SIDE then
		roadList = mainInfo1 and mainInfo1.roadList[roadIndex] 
	else
		roadList = mainInfo2 and mainInfo2.roadList[roadIndex] 
	end

	local roadListLen = roadList and #roadList or 0
	local msgInner = InnerMsg.wl.WL_VALLEY_ROAD_QUERY
	msgInner.uuid = uuid
	msgInner.camp = camp 
	msgInner.roadIndex = roadIndex
	msgInner.playerList = {}
	for i = 1, roadListLen do
		local tuuid = roadList[i]
		msgInner.playerList[#msgInner.playerList + 1] = fontRoadPlayer(tuuid)
	end
	msgInner.myData = fontRoadPlayer(uuid) or {}
	InnerMsg.sendMsg(fd, msgInner)
end

-- 封装鼓舞信息
function fontInspireData(dataNet, round, mainInfo1, mainInfo2, uuid)
	dataNet.round = round
	dataNet.mainInfo1 = copyWLMainInfo(mainInfo1)
	dataNet.mainInfo2 = copyWLMainInfo(mainInfo2)
	dataNet.selectIndex = getInspireIndex(mainInfo1, uuid)
end

-- 鼓舞查询
function LW_VALLEY_INSPIRE_QUERY(fd, uuid)
	local state = ValleyLogic.getState()
	if state ~= ValleyLogic.STATE_ACT_FIGHT then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_INSPIRE_ERR_TIME)
	end
	local round, roundState = ValleyLogic.getRound()
	if roundState ~= ValleyLogic.STATE_FIGHT_READY then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_INSPIRE_ERR_TIME)
	end

	local mainInfo1 = getMainInfo(svrIndex1)
	local svrIndex2 = mainInfo1 and mainInfo1.targetSvrIndex
	local mainInfo2 = getMainInfo(svrIndex2)
	-- 战斗提前结束
	if isAllFightEnd(mainInfo1) or isAllFightEnd(mainInfo2) then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_ERR_FINISH)
	end

	local msgInner = InnerMsg.wl.WL_VALLEY_INSPIRE_QUERY
	msgInner.uuid = uuid
	msgInner.data = msgInner.data or {}
	Util.cleanTable(msgInner.data)
	fontInspireData(msgInner.data, round, mainInfo1, mainInfo2, uuid)
	InnerMsg.sendMsg(fd, msgInner)
end

-- 鼓舞
function LW_VALLEY_INSPIRE(fd, uuid, selectIndex)
	local state = ValleyLogic.getState()
	if state ~= ValleyLogic.STATE_ACT_FIGHT then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_INSPIRE_ERR_TIME)
	end
	local round, roundState = ValleyLogic.getRound()
	if roundState ~= ValleyLogic.STATE_FIGHT_READY then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_INSPIRE_ERR_TIME)
	end
	local mainInfo1 = getMainInfo(svrIndex1)
	local svrIndex2 = mainInfo1 and mainInfo1.targetSvrIndex
	local mainInfo2 = getMainInfo(svrIndex2)
	-- 战斗提前结束
	if isAllFightEnd(mainInfo1) or isAllFightEnd(mainInfo2) then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_ERR_FINISH)
	end
	-- 是否进行过鼓舞
	if getInspireIndex(mainInfo1, uuid)	then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_INSPIRE_ERR_HAD)
	end

	setInspireIndex(mainInfo1, uuid, selectIndex)
	LW_VALLEY_INSPIRE_QUERY(fd, uuid)
end

-- 封装观战界面-玩家信息
function fontFightPlayerNet(playerData1, playerData2, isWin)
	if not playerData1 or not playerData2 then return end

	local fightPlayer = {}
	fightPlayer.roleBase = {}
	RoleLogic.makeRoleBase(playerData1.rolebase, fightPlayer.roleBase)
	local inspireCnt1 = playerData1.rolebase.inspireCnt
	local inspireCnt2 = playerData2.rolebase.inspireCnt
	fightPlayer.attrsUp = getAttrsUp(inspireCnt1, inspireCnt2, CombatDefine.ATTACK_SIDE)
	fightPlayer.attrsUp = fightPlayer.attrsUp or {}
	fightPlayer.attrsUp[0] = #fightPlayer.attrsUp
	fightPlayer.tili = playerData1.rolebase.tili
	fightPlayer.isWin = isWin and 1 or 0
	fightPlayer.heroList = {[0] = 0}
	for index, obj in pairs(playerData1.objList) do
		fightPlayer.heroList[0] = fightPlayer.heroList[0] + 1
		local heroNet = fightPlayer.heroList[fightPlayer.heroList[0]]
		HeroGrid.makeHeroSimple(heroNet, obj, index)
	end
	return fightPlayer
end

-- 封装双方基础信息
function fontFightBaseNet(mainInfo, roadIndex)
	if not mainInfo then return end

	local fightBase = {}
	local fightIndex = mainInfo.fightIndexList[roadIndex] or 1
	fightBase.svrName = mainInfo.svrName
	fightBase.maxCnt = #mainInfo.roadList
	fightBase.leftCnt = fightBase.maxCnt - fightIndex + 1
	return fightBase
end

-- 观战界面
function LW_VALLEY_FIGHT_QUERY(fd, uuid, roadIndex)
	local state = ValleyLogic.getState()
	if state ~= ValleyLogic.STATE_ACT_FIGHT then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_FIGHT_ERR_TIME)
	end
	local round, roundState = ValleyLogic.getRound()
	if roundState ~= ValleyLogic.STATE_FIGHT_FIGHT then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_FIGHT_ERR_TIME)
	end
	local mainInfo1 = getMainInfo(svrIndex1)
	local svrIndex2 = mainInfo1 and mainInfo1.targetSvrIndex
	local mainInfo2 = getMainInfo(svrIndex2)
	-- 战斗提前结束
	if isAllFightEnd(mainInfo1) or isAllFightEnd(mainInfo2) then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.VALLEY_ERR_FINISH)
	end

	local msgInner = InnerMsg.wl.WL_VALLEY_FIGHT_QUERY
	msgInner.uuid = uuid
	msgInner.data = msgInner.data or {}
	Util.cleanTable(msgInner.data)
	fontInspireData(msgInner.data, round, mainInfo1, mainInfo2, uuid)	
	local uuid1 = getMovePlayerUuid(mainInfo1, roadIndex, 1)
	local uuid2 = getMovePlayerUuid(mainInfo2, roadIndex, 1)
	local isWin1 = mainInfo1.fightResult and mainInfo1.fightResult[roadIndex]
	local isWin2 = mainInfo2.fightResult and mainInfo2.fightResult[roadIndex]
	local playerData1 = getPlayerData(uuid1)
	local playerData2 = getPlayerData(uuid2)
	local fightPlayer1 = fontFightPlayerNet(playerData1, playerData2, isWin1)
	local fightPlayer2 = fontFightPlayerNet(playerData2, playerData1, isWin2)	
	if fightPlayer1 and fightPlayer2 then
		msgInner.data.fightPlayers = {[0] = 2}
		msgInner.data.fightPlayers[1] = fightPlayer1
		msgInner.data.fightPlayers[2] = fightPlayer2
	end
	local videoUuid = mainInfo1.fightVideo and mainInfo1.fightVideo[roadIndex]
	msgInner.data.fightState = videoUuid and 1 or 0 --战斗结果出来了
	msgInner.data.videoUuid = videoUuid
	msgInner.data.fightBase[0] = 2
	msgInner.data.fightBase[1] = fontFightBaseNet(mainInfo1, roadIndex)
	msgInner.data.fightBase[2] = fontFightBaseNet(mainInfo2, roadIndex)
	InnerMsg.sendMsg(fd, msgInner)
end

-- 观战
function LW_VALLEY_PLAY_FIGHT(fd, uuid, videoUuid)
	local combatInfo = getCombatInfo(videoUuid)
	if not combatInfo then
		return MiddleLogic.sendWLBroadcast(fd, uuid, Lang.COMBAT_ERR_NOT_VIDEO)
	end

	local msgInner = InnerMsg.wl.WL_VALLEY_PLAY_FIGHT
	msgInner.uuid = uuid
	msgInner.combatInfo = combatInfo
	InnerMsg.sendMsg(fd, msgInner)
end

-- 比较胜利次数
local function cmpWinCnt(a, b)
	if a.winCnt ~= b.winCnt then
		return a.winCnt > b.winCnt
	end
	return a.time < b.time
end

-- 刷新排行榜
function sortBoard(mainInfo)
	if not mainInfo then return end

	local list = {}
	for _, list in pairs(mainInfo.roadList) do
		for _, uuid in ipairs(list) do
			local playerData = getPlayerData(uuid, FieldsRoleBase)
			if playerData then
				list[#list + 1] = playerData.rolebase
			end
		end
	end	
	if #list > 1 then
		table.sort(list, cmpWinCnt)
	end
	mainInfo.board = {}
	for i = 1, #list do
		mainInfo.board[i] = list[i].uuid
	end
end

-- 战斗结果
function LW_VALLEY_COMBATINFO(fd, svrIndex1, combatInfo)
	local mainInfo1 = getMainInfo(svrIndex1)
	local svrIndex2 = mainInfo1 and mainInfo1.targetSvrIndex
	local mainInfo2 = getMainInfo(svrIndex2)
	if not mainInfo1 or not mainInfo2 then 
		return -- 不可能哦，不过加一下预防
	end

	local uuid1 = combatInfo.attacker.uuid
	local uuid2 = combatInfo.defender.uuid
	local playerData1 = getPlayerData(uuid1, FieldsRoleBase)
	local playerData2 = getPlayerData(uuid2, FieldsRoleBase)
	if not playerData1 or not not playerData2 then
		return
	end

	-- 保存战斗结果
	combatInfo.svrIndex1 = svrIndex1
	combatInfo.svrIndex2 = svrIndex2
	combatInfo.tili1 = playerData1.rolebase.tili
	combatInfo.tili2 = playerData2.rolebase.tili

	-- 修改胜利场次 体力 剩余血量等信息
	if combatInfo.isWin then
		playerData1.rolebase.winCnt = playerData1.rolebase.winCnt + 1				
	else
		playerData2.rolebase.winCnt = playerData2.rolebase.winCnt + 1	
	end
	playerData1.hpRateList = combatInfo.hpRateListAtk
	playerData2.hpRateList = combatInfo.hpRateListDef	
	playerData1.rolebase.tili = playerData1.rolebase.tili - 1
	playerData1.rolebase.time = os.time()
	playerData2.rolebase.tili = playerData2.rolebase.tili - 1
	playerData2.rolebase.time = os.time()
	upsetPlayerData(playerData1)
	upsetPlayerData(playerData2)

	-- 记录到日志中
	addLog(combatInfo, mainInfo1, mainInfo2)
	solveLog(CombatDefine.ATTACK_SIDE, mainInfo1, combatInfo, playerData1)
	solveLog(CombatDefine.DEFEND_SIDE, mainInfo2, combatInfo, playerData2)

	-- 刷新排行榜
	sortBoard(mainInfo1)
	sortBoard(mainInfo2)
	ValleyLogic.saveCommonDB(ValleyLogic.getCommonDB())
end

-- 日志
function LW_VALLEY_LOG_QUERY(fd, uuid, roadIndex)
	local svrIndex = MiddleManager.FD_2_SVRINDEX[fd]
	if not svrIndex then return end

	local mainInfo = getMainInfo(svrIndex)
	local logsLen = mainInfo and #mainInfo.logs or 0

	local msgInner = InnerMsg.wl.WL_VALLEY_LOG_QUERY
	msgInner.uuid = uuid
	msgInner.roadIndex = roadIndex
	msgInner.logs = msgInner.logs or {}
	Util.cleanTable(msgInner.logs)
	for i = 1, logsLen do
		local videoUuid = mainInfo.logs[i]
		local combatInfo = getCombatInfo(videoUuid, FilldsCombatLog)
		if combatInfo then
			if (roadIndex == 0 and (-- 自己的
					combatInfo.attacker.uuid == uuid or 
					combatInfo.defender.uuid == uuid)) or 
				(roadIndex > 0 and -- 某路的
					combatInfo.roadIndex == roadIndex) then
				local log = {}
				log.time = combatInfo.time 
				log.roleBase1 = combatInfo.attacker
				log.roleBase2 = combatInfo.defender
				log.tili1 = combatInfo.tili1
				log.tili2 = combatInfo.tili2
				log.isWin = combatInfo.isWin and 1 or 0
				msgInner.logs[#msgInner.logs + 1] = log
			end
		end
	end
	InnerMsg.sendMsg(fd, msgInner)
end

-- 获取排行榜名次
function getRank(mainInfo, uuid)
	if not mainInfo then return end
	for rank, tuuid in ipairs(mainInfo.board) do
		if tuuid == uuid then
			return rank
		end
	end
end

-- 封装排行榜结构体
function fontBoardNet(uuid, rank)
	local playerData = getPlayerData(uuid, FieldsRoleBase)
	local net = {}	
	net.rank = rank or 0
	if playerData then
		net.killCnt = playerData.rolebase.winCnt or 0
		net.roleBase = {}
		RoleLogic.makeRoleBase(playerData.rolebase, net.roleBase)
	end
	return net
end

-- 排行榜
function LW_VALLEY_BOARD_QUERY(fd, uuid, camp)
	local svrIndex1 = MiddleManager.FD_2_SVRINDEX[fd]
	if not svrIndex1 then return end

	local mainInfo1 = getMainInfo(svrIndex1)
	local svrIndex2 = mainInfo1 and mainInfo1.targetSvrIndex
	local mainInfo2 = getMainInfo(svrIndex2)
	local mainInfo = mainInfo1
	if camp ~= CombatDefine.ATTACK_SIDE then
		mainInfo = mainInfo2
	end
	local boardLen = mainInfo and #mainInfo.board or 0
	local msgInner = InnerMsg.wl.WL_VALLEY_BOARD_QUERY
	msgInner.uuid = uuid
	msgInner.camp = camp 
	msgInner.list = msgInner.list or {}
	Util.cleanTable(msgInner.list)
	for i = 1, boardLen do
		if #msgInner.list >= MAX_BOARD_LEN then
			break
		end
		local tuuid = mainInfo.board[i]
		msgInner.list[#msgInner.list + 1] = fontBoardNet(tuuid, i)
	end
	local myRank = getRank(mainInfo1, uuid)
	msgInner.myData = fontBoardNet(uuid, myRank)	
	InnerMsg.sendMsg(fd, msgInner)
end

------------------------------------- 活动状态变化 ------------------------------------------
-- 按照战力排序
local function cmpZDL(a, b)
	if a.zhandouli ~= b.zhandouli then
		return a.zhandouli > b.zhandouli
	end
	return a.svrIndex < b.svrIndex
end

-- 初始匹配组信息
local function createMatchData(svrIndex1, svrIndex2)
	if (not svrIndex1) and (not svrIndex2) then return end
	local matchData = {}
	matchData.svrIndex1 = svrIndex1 or 0
	matchData.svrIndex2 = svrIndex2 or 0
	return matchData
end

-- 匹配对手 按战力排序(从高到低下) 两两匹配
function matchMainInfo()
	local list = {}
	local commonDB = ValleyLogic.getCommonDB()
	if commonDB.mainInfos then
		for _, data in pairs(commonDB.mainInfos) do
			list[#list + 1] = data
		end
	end
	if #list > 1 then
		table.sort(list, cmpZDL)
	end
	commonDB.matchList = {}
	for i = 1, #list, 2 do
		local data1 = list[i]
		local data2 = list[i + 1]
		if data1 then
			data1.targetSvrIndex = data2 and data2.svrIndex or 0
		end
		if data2 then
			data2.targetSvrIndex = data1 and data1.svrIndex or 0
		end
		local matchData = createMatchData(data1 and data1.svrIndex, data2 and data2.svrIndex)
		commonDB.matchList[#commonDB.matchList + 1] = matchData
	end
	ValleyLogic.saveCommonDB(commonDB)
end

-- 侦查开始/匹配结束
function onActExplore()
	matchMainInfo()
end

-- 发送破营+杀敌奖励
function sendWLFinalResult(mainInfo, winCnt, failCnt)
	local fd = MiddleManager.getFDBySvrIndex(mainInfo.svrIndex)
	if not fd then return end

	local msgInner = InnerMsg.wl.WL_VALLEY_FINAL_RESULT
	msgInner.winCnt = winCnt
	msgInner.failCnt = failCnt 
	msgInner.tieCnt = ValleyLogic.ROAD_MAX_CNT - winCnt - failCnt
	msgInner.killList = {}
	for _, list in pairs(mainInfo.roadList) do
		for _, uuid in ipairs(list) do
			local playerData = getPlayerData(uuid, FieldsRoleBase)
			if playerData then
				msgInner.killList[uuid] = playerData.rolebase.winCnt
			end
		end
	end
	InnerMsg.sendMsg(fd, msgInner)
end

-- 活动结束
function onActEnd()
	-- 发送破营+杀敌奖励
	local commonDB = ValleyLogic.getCommonDB()
	if commonDB.matchList then
		for _, matchData in ipairs(commonDB.matchList) do
			local svrIndex1 = matchData.svrIndex1
			local svrIndex2 = matchData.svrIndex2
			local mainInfo1 = getMainInfo(svrIndex1)
			local mainInfo2 = getMainInfo(svrIndex2)
			local star1 = ValleyLogic.getMainStar(mainInfo1, mainInfo2)
			local star2 = ValleyLogic.getMainStar(mainInfo2, mainInfo1)
			sendWLFinalResult(mainInfo1, star1, star2)
			sendWLFinalResult(mainInfo2, star2, star1)
		end
	end
	ValleyLogic.cleanDB()
end

-- 活动开始
function onActStart()
	ValleyLogic.cleanDB()
end

-- 发送鼓舞结果
function sendWLInspireResult(mainInfo)
	local fd = MiddleManager.getFDBySvrIndex(mainInfo.svrIndex)
	if not fd then return end
	if not mainInfo.inspireList then return end

	local msgInner = InnerMsg.wl.WL_VALLEY_INSPIRE_RESULT
	msgInner.winCnt = mainInfo.fightWinCnt
	msgInner.failCnt = mainInfo.fightFailCnt
	msgInner.inspireList = mainInfo.inspireList
	InnerMsg.sendMsg(fd, msgInner)
end

-- 行军开始/前一轮结束
function onRoundEnd()
	local commonDB = ValleyLogic.getCommonDB()
	if not commonDB.mainInfos then return end

	for _, mainInfo in pairs(commonDB.mainInfos) do
		-- 退场 失败或者体力为0
		local fightIndexChange = mainInfo.fightIndexChange
		mainInfo.fightIndexChange = nil
		if fightIndexChange then
			for roadIndex in pairs(fightIndexChange) do
				local oldFightIndex = mainInfo.fightIndexList[roadIndex] or 1
				mainInfo.fightIndexList[roadIndex] = oldFightIndex + 1
			end
		end
		-- 发送鼓舞奖励
		sendWLInspireResult(mainInfo)
		-- 重置鼓舞信息+本轮胜场
		mainInfo.fightWinCnt = 0
		mainInfo.fightFailCnt = 0
		mainInfo.inspireCnt = nil 
		mainInfo.inspireList = nil 	
		mainInfo.fightResult = nil
		mainInfo.fightVideo = nil	
	end
	ValleyLogic.saveCommonDB(ValleyLogic.getCommonDB())
end

-- 行军结束 
function onMoveEnd()
	local commonDB = ValleyLogic.getCommonDB()
	if not commonDB.mainInfos then return end

	-- 移动到目标点
	for _, mainInfo in pairs(commonDB.mainInfos) do
		for roadIndex = 1, ValleyLogic.ROAD_MAX_CNT do
			for index = 1, ValleyLogic.ROAD_POINT_CNT do
				local uuid = getMovePlayerUuid(mainInfo, roadIndex, index)
				if uuid then
					mainInfo.moveList[uuid] = getMoveToPos(index)
				end
			end
		end
	end	
	ValleyLogic.saveCommonDB(ValleyLogic.getCommonDB())
end

-- 发送战斗开打
function sendWLCombatBegin(round, roadIndex, mainInfo1, mainInfo2, playerData1, playerData2)
	if not playerData1 or not playerData2 then
		return
	end

	local fd = MiddleManager.getFDBySvrIndex(mainInfo1.svrIndex)
	fd = fd or MiddleManager.getFDBySvrIndex(mainInfo2.svrIndex)
	if not fd then return end

	local msgInner = InnerMsg.wl.WL_VALLEY_COMBAT_BEGIN
	msgInner.svrIndex = mainInfo1.svrIndex
	msgInner.roadIndex = roadIndex
	msgInner.round = round
	msgInner.inspireCnt1 = mainInfo1.inspireCnt or 0
	msgInner.inspireCnt2 = mainInfo2.inspireCnt or 0
	msgInner.playerData1 = playerData1
	msgInner.playerData2 = playerData2
	InnerMsg.sendMsg(fd, msgInner)
end

-- 开始战斗
function onFightBegin(round)
	local commonDB = ValleyLogic.getCommonDB()
	if not commonDB.matchList then return end

	for _, matchData in ipairs(commonDB.matchList) do
		local svrIndex1 = matchData.svrIndex1
		local svrIndex2 = matchData.svrIndex2
		local mainInfo1 = getMainInfo(svrIndex1)
		local mainInfo2 = getMainInfo(svrIndex2)
		for roadIndex = 1, ValleyLogic.ROAD_MAX_CNT do
			local uuid1 = getMovePlayerUuid(mainInfo1, roadIndex, 1)
			local playerData1 = getPlayerData(uuid1)
			local uuid2 = getMovePlayerUuid(mainInfo2, roadIndex, 1)
			local playerData2 = getPlayerData(uuid2)
			sendWLCombatBegin(round, roadIndex, mainInfo1, mainInfo2, playerData1, playerData2)
		end
	end
end

-- 切换战斗轮次状态
function onActRound(round, roundState)	
	if roundState == ValleyLogic.STATE_FIGHT_MOVE then	
		-- 行军开始/前一轮结束
		onRoundEnd() 
	elseif roundState == ValleyLogic.STATE_FIGHT_READY then
		-- 鼓舞开始/行军结束
		onMoveEnd()
	elseif roundState == ValleyLogic.STATE_FIGHT_FIGHT then
		-- 开打！！
		onFightBegin(round)
	end
end

